home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / aros / exec / allocate.c < prev    next >
C/C++ Source or Header  |  1996-09-13  |  4KB  |  172 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: allocate.c,v 1.5 1996/09/13 17:51:21 digulla Exp $
  4.     $Log: allocate.c,v $
  5.     Revision 1.5  1996/09/13 17:51:21  digulla
  6.     Use IPTR
  7.  
  8.     Revision 1.4  1996/08/13 13:55:57  digulla
  9.     Replaced __AROS_LA by __AROS_LHA
  10.     Replaced some __AROS_LH*I by __AROS_LH*
  11.     Sorted and added includes
  12.  
  13.     Revision 1.3  1996/08/01 17:41:04  digulla
  14.     Added standard header for all files
  15.  
  16.     Desc:
  17.     Lang:
  18. */
  19. #include "exec_intern.h"
  20. #include "memory.h"
  21. #include "machine.h"
  22. #include <exec/alerts.h>
  23. #include <aros/libcall.h>
  24.  
  25. /*****************************************************************************
  26.  
  27.     NAME */
  28.     #include <exec/memory.h>
  29.     #include <clib/exec_protos.h>
  30.  
  31. __AROS_LH2(APTR, Allocate,
  32.  
  33. /*  SYNOPSIS */
  34.     __AROS_LHA(struct MemHeader *, freeList, A0),
  35.     __AROS_LHA(ULONG,              byteSize, D0),
  36.  
  37. /*  LOCATION */
  38.     struct ExecBase *, SysBase, 31, Exec)
  39.  
  40. /*  FUNCTION
  41.     Allocate memory out of a private region handled by the MemHeader
  42.     structure.
  43.  
  44.     INPUTS
  45.     freeList - Pointer to the MemHeader structure which holds the memory
  46.     byteSize - Number of bytes you want to get
  47.  
  48.     RESULT
  49.     A pointer to the number of bytes you wanted or NULL if the memory
  50.     couldn't be allocated
  51.  
  52.     NOTES
  53.     The memory is aligned to sizeof(struct MemChunk). All requests
  54.     are rounded up to a multiple of that size.
  55.  
  56.     EXAMPLE
  57.     #define POOLSIZE 4096
  58.     \* Get a MemHeader structure and some private memory *\
  59.     mh=(struct MemHeader *)
  60.         AllocMem(sizeof(struct MemHeader)+POOLSIZE,MEMF_ANY);
  61.     if(mh!=NULL)
  62.     {
  63.         \* Build a private pool *\
  64.         mh->mh_First=(struct MemChunk *)(mh+1);
  65.         mh->mh_First->mc_Next=NULL;
  66.         mh->mh_First->mc_Bytes=POOLSIZE;
  67.         mh->mh_Free=POOLSIZE;
  68.         {
  69.         \* Use the pool *\
  70.         UBYTE *mem1,*mem2;
  71.         mem1=Allocate(mh,1000);
  72.         mem2=Allocate(mh,2000);
  73.         \* Do something with memory... *\
  74.         }
  75.         \* Free everything at once *\
  76.         FreeMem(mh,sizeof(struct MemHeader)+POOLSIZE);
  77.     }
  78.  
  79.     BUGS
  80.  
  81.     SEE ALSO
  82.     Deallocate()
  83.  
  84.     INTERNALS
  85.  
  86.     HISTORY
  87.     17-09-95    created by m. fleischer
  88.     16-10-95    increased portability
  89.  
  90. ******************************************************************************/
  91. {
  92.     __AROS_FUNC_INIT
  93.     struct MemChunk *p1, *p2;
  94.  
  95.     /* Zero bytes requested? May return everything ;-). */
  96.     if(!byteSize)
  97.     return NULL;
  98.  
  99.     /* First round byteSize to a multiple of MEMCHUNK_TOTAL. */
  100.     byteSize=(byteSize+MEMCHUNK_TOTAL-1)&~(MEMCHUNK_TOTAL-1);
  101.  
  102.     /* Is there enough free memory in the list? */
  103.     if(freeList->mh_Free<byteSize)
  104.     return NULL;
  105.  
  106.     /*
  107.     The free memory list is only single linked, i.e. to remove
  108.     elements from the list I need the node as well as it's
  109.     predessor. For the first element I can use freeList->mh_First
  110.     instead of a real predessor.
  111.     */
  112.     p1=(struct MemChunk *)&freeList->mh_First;
  113.     p2=p1->mc_Next;
  114.  
  115.     /* Is the list enpty? */
  116.     if(p2==NULL)
  117.     return NULL;
  118.  
  119.     /* Follow the list */
  120.     for(;;)
  121.     {
  122. #if !defined(NO_CONSISTENCY_CHECKS)
  123.     /* Consistency check: Check alignment restrictions */
  124.     if( ((IPTR)p2|(ULONG)p2->mc_Bytes) & (MEMCHUNK_TOTAL-1) )
  125.     {
  126.         Alert(AN_MemCorrupt);
  127.         return NULL;
  128.     }
  129. #endif
  130.     /* Check if current block is large enough */
  131.     if(p2->mc_Bytes>=byteSize)
  132.     {
  133.         /* It is. Remove it from the list and return it. */
  134.         if(p2->mc_Bytes==byteSize)
  135.         /* Fits exactly. Just relink the list. */
  136.         p1->mc_Next=p2->mc_Next;
  137.         else
  138.         {
  139.         /* Split the current chunk and return the first bytes. */
  140.         p1->mc_Next=(struct MemChunk *)((UBYTE *)p2+byteSize);
  141.         p1=p1->mc_Next;
  142.         p1->mc_Next=p2->mc_Next;
  143.         p1->mc_Bytes=p2->mc_Bytes-byteSize;
  144.         }
  145.         /* Adjust free memory count and return */
  146.         freeList->mh_Free-=byteSize;
  147.         return p2;
  148.     }
  149.  
  150.     /* Go to next block */
  151.     p1=p2;
  152.     p2=p1->mc_Next;
  153.  
  154.     /* Check if this was the end */
  155.     if(p2==NULL)
  156.         return NULL;
  157. #if !defined(NO_CONSISTENCY_CHECKS)
  158.     /*
  159.         Consistency check:
  160.         If the end of the last block+1 is bigger or equal to
  161.         the start of the current block something must be wrong.
  162.     */
  163.     if((UBYTE *)p2<=(UBYTE *)p1+p1->mc_Bytes)
  164.     {
  165.         Alert(AN_MemCorrupt);
  166.         return NULL;
  167.     }
  168. #endif
  169.     }
  170.     __AROS_FUNC_EXIT
  171. } /* Allocate */
  172.